package org.nf.trading.service.app.circle.impl;


import lombok.RequiredArgsConstructor;
import org.nf.trading.dao.LikeMapper;
import org.nf.trading.dto.LikeDTO;
import org.nf.trading.entity.Like;
import org.nf.trading.service.app.circle.LikeService;
import org.nf.trading.service.app.circle.enums.RedisKeyEnum;
import org.nf.trading.service.app.circle.mq.LikeSyncProducer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author wangl
 * @date 2023/12/7
 */
@Service
@RequiredArgsConstructor
public class LikeServiceImpl implements LikeService {

    private final LikeMapper likeMapper;

    private final RedisTemplate<String, Integer> redisTemplate;

    private final LikeSyncProducer producer;

    @Override
    public LikeDTO like(int postId, int userId) {
        boolean likeStatus = false;
        //如果缓存中存在用户id则取消点赞，不存在则添加用户id记录点赞
        if(isLike(postId, userId)) {
            //将用户ID从set集合中移除
            redisTemplate.opsForSet()
                    .remove(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId, userId);
        } else {
            likeStatus = true;
            //将用户ID添加到set集合中
            redisTemplate.opsForSet()
                    .add(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId, userId);
        }
        LikeDTO likeDTO = new LikeDTO(likeStatus, postId, userId, likeCount(postId));
        //异步更新到数据库
        producer.send(likeDTO);
        return likeDTO;
    }

    @Override
    public Boolean isLike(int postId, int userId) {
        //如果缓存中没有则先从数据库点赞表拉取当前帖子的点赞用户并缓存
        if(Boolean.FALSE.equals(redisTemplate.hasKey(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId))) {
            List<Like> list = likeMapper.listLikeByPostId(postId);
            //将所有对当前贴子点赞的用户ID保存到redis的set集合中
            list.forEach(like -> redisTemplate.opsForSet()
                    .add(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId, like.getUserId()));
            //设置过期时间
            redisTemplate.expire(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId, 72, TimeUnit.HOURS);
        }
        return redisTemplate.opsForSet()
                .isMember(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId, userId);
    }

    @Override
    public Long likeCount(int postId) {
        return redisTemplate.opsForSet()
                .size(RedisKeyEnum.POST_LIKE_PREFIX.getValue() + postId);
    }
}